#include "stdafx.h"  

namespace Melting
{
	
	//-------------------------------------------------------------------------------------
	//-------------------------------------------------------------------------------------
	PackFile::PackFile( void ) 
	:	mbIsOpen		( false )
	,	mulFileCount	( 0 )
	,	maFileInfo		( nullptr )
	,	mPackFile		( )
	{ 
	}
	
	//-------------------------------------------------------------------------------------
	//-------------------------------------------------------------------------------------
	PackFile::PackFile( const PackFilePath _strPackFilePath ) 
	:	mbIsOpen	( false )
	,	mulFileCount( 0 )
	,	maFileInfo	( nullptr )
	,	mPackFile	( )
	{
		Open( _strPackFilePath );	
	}
	
	//-------------------------------------------------------------------------------------
	//-------------------------------------------------------------------------------------
	PackFile::~PackFile( void ) 
	{
		Close( );
		SAFE_DELETE_ARRAY( maFileInfo );
	};
	
	//-------------------------------------------------------------------------------------
	//-------------------------------------------------------------------------------------
	void PackFile::Open( const PackFilePath _strPackFilePath )
	{ 
		if( mPackFile.Open( _strPackFilePath ) )
		{
			mbIsOpen = true;
		}
		else
		{
			MB_ASSERT( false, "Can not open the file s", _strPackFilePath );
			return;
		}
		
		// read the pack file header
		mPackFile.Read( mulFileCount );
		
		MB_ASSERT( mulFileCount > 0, " The pack does not contain files!" );
		
		maFileInfo = new FileInfo[ mulFileCount ];
		for( ULONG i = 0; i < mulFileCount; ++i )
		{
			mPackFile.Read( maFileInfo[ i ].mulOffset );
			mPackFile.Read( maFileInfo[ i ].mulSize );
		}	
		
		//--------------------
		// post condition
		MB_ASSERT( maFileInfo != nullptr, "Can not load the pack file." );
		//--------------------
	}
	 
	//-------------------------------------------------------------------------------------
	//-------------------------------------------------------------------------------------
	void PackFile::ReadFile( ULONG _ulIndex,  UBYTE* _pubBuffer, ULONG _ulSizeOfBuffer, ULONG _ulOffsetInFile, ULONG _ulBytesToRead )
	{
		//--------------------
		// pre condition
		MB_ASSERT( mbIsOpen == true, 		"The pack file is not opened!" );
		MB_ASSERT( _ulIndex < mulFileCount, "Index is out of range" );
		//--------------------
		
		// get its file info
		const FileInfo& fileInfo 		= maFileInfo[ _ulIndex ];
		
		ULONG ulNbBytesToRead = min ( _ulBytesToRead, fileInfo.mulSize );
			
		MB_ASSERT( _ulSizeOfBuffer >= _ulBytesToRead, "The buffer is too small for the requested file." ) ; 
		
		// and read the file
		
		mPackFile.SetPosition( static_cast< long >( fileInfo.mulOffset + _ulOffsetInFile ), Melting::MB_SEEK_SET );
	
		mPackFile.ReadByteArray( ulNbBytesToRead, _pubBuffer );		
	}
	
	//-------------------------------------------------------------------------------------
	//-------------------------------------------------------------------------------------
	void PackFile::ReadFileAndAllocate( ULONG ulIndex, UBYTE*& pubBuffer )
	{
		//--------------------
		// pre condition
		MB_ASSERT( mbIsOpen == true, 		"The pack file is not opened!" );
		MB_ASSERT( ulIndex < mulFileCount, 	"Index is out of range %d / %d", ulIndex, mulFileCount );
		//--------------------
		
		const ULONG ulFileSize = maFileInfo[ ulIndex ].mulSize;
		
		if( pubBuffer != nullptr )
		{
			delete[] pubBuffer;
		}
		
		pubBuffer = new UBYTE[ ulFileSize ];
		
		ReadFile( ulIndex, pubBuffer, ulFileSize );
	} 	
}

